#
# Plots_Primaries_Nom.R
#
# Plots of descriptive relationship of nominee
# to incumbent ideology..
#
# Seth Hill, Sep 2021.
#

rm(list=ls())
if (.Platform$OS == "windows") {
  # Set working directory in location of script on Windows machine.
  .doit <- function() { frame_files <- lapply(sys.frames(), function(x) x$ofile);frame_files <- Filter(Negate(is.null), frame_files); PATH <- dirname(frame_files[[length(frame_files)]]); setwd(PATH) ; rm(PATH,frame_files) }
  try(.doit(),silent=T) # Trap errors
}

library(tidyverse)
library(foreign)
library(bit64)
library(data.table)
options(stringsAsFactors=F,digits=3)
library(RColorBrewer)
palette(brewer.pal(n=9,name="Set1")[c(1:5,7:9)]) # reset default colors
par(cex.lab=1.2,cex.axis=1.2,cex=1.2)
# Fancyaxis for tufte rug. See http://motioninsocial.com/tufte/
library(devtools)
source_url("https://raw.githubusercontent.com/sjmurdoch/fancyaxis/master/fancyaxis.R")  

#
# Functions.
#

centrismScatter <- function(DT,x,y,axes_yes=T,...) {
  # Scatter plot of y on x.
  # Open plot.
  DT[,plot(x=get(x),y=get(y),type='n',ann=F,axes=F,...)]
  # Axes and grid.
  if (axes_yes) { axis(1);axis(2,las=2) }
  grid()
  # Points.
  if (DT[,500 < .N]) {
    # Sample 500 points
    DT[sample(x=seq_len(.N),size=500),points(x=get(x),y=get(y),pch=19,cex=1.2)]
  } else {
    # All points.
    DT[,points(x=get(x),y=get(y),pch=19,cex=1.2)]
  }
  if (0) { # base rugs
    # Rugs.
    DT[,rug(get(x),side=1)];DT[,rug(get(y),side=2)]
  } else { # fancyaxis rugs
    DT[,axisstripchart(get(x), 1)]
    DT[,axisstripchart(get(y), 2)]
  }
  # Loess smooth, catching errors.
  try(s<-DT[,loess.smooth(x=get(x),y=get(y),span=1/3)],silent=T)
  if ("s" %in% ls()) lines(x=s$x,y=s$y,lwd=5,col=4)
}

doPlot <- function(DT1,x_var="incum_nom_d1",y_var="prehsscore", f1="../figures/NomineeOnIncumbentCentrism-Prehsscore.pdf", f2="../figures/NomineeOnIncumbentCentrism-Prehsscore-Partial.pdf", xlab="Incumbent centrism",ylab="Nominee centrism",open_f2=F) {
  # Make two plots.
  f=f1
  pdf(f,height=4,width=8)
  # By year with fixed axis lims.
  xlim = DT1[,range(get(x_var),na.rm=T)]
  ylim = DT1[,range(get(y_var),na.rm=T)]
  par.old = par(mfrow=c(1,3),oma=c(2.1,2.1,0,0),mar=c(0,0,2.1,0),cex.main=1.4,cex.sub=1.4,font.main=1)
  for (yr in sort(DT1[,unique(year)])) {
    if (yr == 1988) next # no pre-primary dates in 1988 file
    centrismScatter(DT=DT1[year ==yr,],x=x_var,y=y_var,axes_yes=F,xlim=xlim,ylim=ylim)
    title(main=yr,line=0)
    title(xlab=xlab,ylab=ylab,outer=T,line=1,cex=2)
  }

  # All years.
  centrismScatter(DT=DT1,x=x_var,y=y_var,axes_yes=F,xlim=xlim,ylim=ylim)
  title(xlab=xlab,ylab=ylab,main="All years")

  par(par.old)
  dev.off()

  #
  # Residualized wrt pres vote share & party-year.
  #
  DT1P = na.omit(DT1[,c("year","state","district","nominee_party",x_var,y_var,"pooled_dem_2p_pres"),with=F])
  lm_x_var = DT1P[,lm(get(x_var) ~ pooled_dem_2p_pres*factor(year)+factor(nominee_party)*factor(year))]
  lm_y_var = DT1P[,lm(get(y_var) ~ pooled_dem_2p_pres*factor(year)+factor(nominee_party)*factor(year))]
  print(summary(lm_x_var))
  print(summary(lm_y_var))
  DT1P[,resid_x_var := resid(lm_x_var)]
  DT1P[,resid_y_var := resid(lm_y_var)]

  # Partial residual plots.
  f=f2
  pdf(f,height=4,width=8)
  # By year with fixed axis lims.
  xlim = DT1P[,range(resid_x_var,na.rm=T)]
  ylim = DT1P[,range(resid_y_var,na.rm=T)]
  par.old = par(mfrow=c(1,3),oma=c(2.1,2.1,0,0),mar=c(0,0,2.1,0),cex.main=1.4,cex.sub=1.4,font.main=1)
  for (yr in sort(DT1P[,unique(year)])) {
    if (yr == 1988) next # no pre-primary dates in 1988 file
    centrismScatter(DT=DT1P[year ==yr,],x="resid_x_var",y="resid_y_var",axes_yes=F,xlim=xlim,ylim=ylim)
    title(main=yr,line=0)
    title(xlab=paste(xlab,"| Pres share"),ylab=paste(ylab,"| Pres share"),outer=T,line=1,cex=2)
  }

  # All hsscores.
  centrismScatter(DT=DT1P,x="resid_x_var",y="resid_y_var",axes_yes=F,xlim=xlim,ylim=ylim)
  title(main="All years", line=0)

  par(par.old)
  dev.off()

  if (open_f2) system2("open",f)
}

#
# %%%%%%%%%%%%%%%%%
# Data from Tables-DiD.do.
# %%%%%%%%%%%%%%%%%
#

#
# Nominee pre-primary centrism on incumbent centrism.
#
# Hall-Snyder pre-primary nominee ideology scores.
DT_HS = fread("../processedData/StataProcessed-Primaries_HS_Nom.csv")
setkey(DT_HS,nominee_party,district_dist_cycle,year)
doPlot(DT_HS,x_var="incum_nom_d1",y_var="prehsscore", f1="../figures/NomineeOnIncumbentCentrism-Prehsscore.pdf", f2="../figures/NomineeOnIncumbentCentrism-Prehsscore-Partial.pdf", xlab="Incumbent centrism",ylab="Nominee pre-primary centrism")

#
# Nominee centrism on incumbent centrism.
#
DT_HS = fread("../processedData/StataProcessed-Primaries_HS_Nom.csv")
setkey(DT_HS,nominee_party,district_dist_cycle,year)
doPlot(DT_HS,x_var="incum_nom_d1",y_var="hsscore", f1="../figures/NomineeOnIncumbentCentrism-Hsscore.pdf", f2="../figures/NomineeOnIncumbentCentrism-Hsscore-Partial.pdf", xlab="Incumbent centrism",ylab="Nominee centrism",open_f2=F)

#
# Number of candidates on incumbent centrism.
#
DT_CONTRIBS = fread("../processedData/StataProcessed-Primaries_Contribs_Nom.csv")
setkey(DT_CONTRIBS,nominee_party,district_dist_cycle,year)

doPlot(DT_CONTRIBS,x_var="incum_nom_d1",y_var="n_centrist_cand", f1="../figures/NomineeOnIncumbentCentrism-NCentristCands.pdf", f2="../figures/NomineeOnIncumbentCentrism-NCentristCands-Partial.pdf", xlab="Incumbent centrism",ylab="Number outparty centrist primary candidates",open_f2=F)

#
# Number party-connected contributors on incumbent centrism.
#
DT_CONTRIBS = fread("../processedData/StataProcessed-Primaries_Contribs_Nom.csv")
setkey(DT_CONTRIBS,nominee_party,district_dist_cycle,year)

doPlot(DT_CONTRIBS,x_var="incum_nom_d1",y_var="party_donors", f1="../figures/NomineeOnIncumbentCentrism-PartyDonors.pdf", f2="../figures/NomineeOnIncumbentCentrism-PartyDonors-Partial.pdf", xlab="Incumbent centrism",ylab="Number party-connected contributors (log scale)",open_f2=F)

#
# Nominee CF score on incumbent centrism.
#
DT_CF = fread("../processedData/StataProcessed-Primaries_CF_Nom.csv")
setkey(DT_CF,nominee_party,district_dist_cycle,year)
# Drop huge outliers.
flag = DT_CF[,-2.5 < recipientcfscore & recipientcfscore < 2]
cat("Dropping",sum(!flag),"CF score cases outside of [-2.5,2].\n")
DT_CF = DT_CF[flag,]

doPlot(DT_CF,x_var="incum_nom_d1",y_var="recipientcfscore", f1="../figures/NomineeOnIncumbentCentrism-CFscore.pdf", f2="../figures/NomineeOnIncumbentCentrism-CFscore-Partial.pdf", xlab="Incumbent centrism",ylab="Nominee CF centrism",open_f2=F)

